using System;
using System.Collections.Generic;
using System.Xml;
using System.Net;
using TALoaders;
using TAAlert.CommonUtils;

namespace TAAlert.Alerts
{
    class EMAAlert : Alert
    {
        private static readonly string N_EMA_XML = "nEMA";
        private double ema0M;       // Yesterday's EMA
        private double price0M;     // Yesterday's price
        private int nEmaM;          // EMA period
        private DateTime lastHistDateM; // the last date of the historical prices

        // This constructor is used with any External Data loaders (e.g. Yahoo, Bloomberg or Test)
        public EMAAlert(BaseLoader loader, string ticker, int nEMA)
            : base(loader, ticker, StrategyName.EMA)
        {
            nEmaM = nEMA;
            this.commonConstructor();
        }

        /// <summary>Constructor alert from  Xml-code</summary>
        /// <param name="r">XmlReader open with EMA node</param>
        public EMAAlert(XmlReader r)
            : base(r, StrategyName.EMA)
        {
            nEmaM = r.ReadElementContentAsInt(N_EMA_XML,"");
            r.ReadEndElement();
            this.commonConstructor();
        }

        /// <summary>Common part of all constructors</summary>
        private void commonConstructor()
        {
            DateTime end = DateTime.Now.Date.AddDays(-1); // trunc all time information
            DateTime start = end.AddDays(-7 * nEmaM);
            SortedList<DateTime, double> hPrice;
            try
            {
                 hPrice = loaderM.getHistoricalPrices(this.Ticker, start, end, QuoteType.AdjClose);
            }
            catch (WebException wex)
            {
                throw new WebException("EMAAlert: Cannot load ticker: '" + base.Ticker + "' using loader:" + base.loaderM.Loader + "\n" + wex.Message);
            }

            List<double> hEMA = EMAEvaluator.calcEMAArray(hPrice.Values, nEmaM);

            price0M = hPrice.Values[hPrice.Count - 1];
            ema0M = hEMA[hEMA.Count - 1];
            lastHistDateM = hPrice.Keys[hPrice.Count - 1];
        }

        // Latest signal value
        public override Signal evalAlert(out string[] info)
        {
            string timeStamp;
            double price1 = loaderM.getLastPrice(this.Ticker, out timeStamp);
            double ema1 = EMAEvaluator.calcEMA(ema0M, nEmaM, price1);

            info = new string[5];
            info[0] = string.Format("Price = {0:.####}       (as of {1})", price1, timeStamp);
            info[1] = string.Format("EMA({0}) = {1:.####}", nEmaM, ema1);
            info[2] = "Old Signal = " + this.oldAlert();
            info[3] = string.Format("Old Price = {0:.####}   (as of {1})", price0M, lastHistDateM.ToShortDateString());
            info[4] = string.Format("Old EMA({0}) = {1:.####}", nEmaM, ema0M);

            return EMAEvaluator.emaSignal(price1, ema1);
        }

        // Yesterday's signal value
        public override Signal oldAlert()
        {
            return EMAEvaluator.emaSignal(price0M, ema0M);
        }

        public override void  writeXml(XmlWriter writer)
        {
            base.writeXml(writer);
 	        writer.WriteElementString(N_EMA_XML,nEmaM.ToString());
        }

        public override string Description
        {
            get
            {
                return string.Format("{0,-8}: nEMA={1,-8}", base.XmlName, nEmaM);
            }
        }
    }
}
